﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Terminal.Advanced_AEUC_settings_controls.Settings_Interfaces;
using Terminal.Advanced_AEUC_settings_controls.Settings_AUX;
using Terminal.Advanced_AEUC_settings_controls.Settings_Editing_Forms;
using Terminal.Advanced_AEUC_settings_controls.Setting_Advanced_Control;
using Auxiliaries;

namespace Terminal.Advanced_AEUC_settings_controls.Settings_AUX
{
    /// <summary>
    /// Parameter structure and parameter fields information
    /// </summary>
    public class GenPayloadStruct
    {
        /// <summary>
        /// Object to add to an existing payload - when creating run time variables
        /// </summary>
        public class NewPldItem : IAEUCSetting
        {
            /// <summary>
            /// Payload item constructor
            /// </summary>
            public NewPldItem()
            {
                Val = 0;
                ValOpt = 0;
                ValDef = 0;
                ValMin = long.MinValue;
                ValMax = long.MaxValue;
                Id = 0;
                Size = 4;
                Enabled = true;
                DisplayName = "Run Time Var";
            }

            long Val;
            long ValOpt;
            long ValDef;
            long ValMin;
            long ValMax;
            uint Id;
            uint Size;
            bool Enabled;
            bool aeuc_refPtr;
            string DisplayName;

            #region IAEUCSetting Members
            /// <summary>
            /// Primary value of the setting
            /// </summary>
            public long AEUC_Val
            {
                get
                {
                    return Val;
                }
                set
                {
                    Val = value;
                }
            }
            /// <summary>
            /// Optional value of the setting
            /// </summary>
            public long AEUC_OptVal
            {
                get
                {
                    return ValOpt;
                }
                set
                {
                    ValOpt = value;
                }
            }
            /// <summary>
            /// Default value
            /// </summary>
            public long AEUC_Default
            {
                get
                {
                    return ValDef;
                }
                set
                {
                    ValDef = value;
                }
            }
            /// <summary>
            /// Minimum possible value
            /// </summary>
            public long AEUC_Min
            {
                get
                {
                    return ValMin;
                }
                set
                {
                    ValMin = value;
                }
            }
            /// <summary>
            /// Maximum possible value
            /// </summary>
            public long AEUC_Max
            {
                get
                {
                    return ValMax;
                }
                set
                {
                    ValMax = value;
                }
            }
            /// <summary>
            /// AEUC setting Id
            /// </summary>
            public uint AEUC_Id
            {
                get
                {
                    return Id;
                }
                set
                {
                    Id = value;
                }
            }
            /// <summary>
            /// AEUC setting size
            /// </summary>
            public uint AEUC_Size
            {
                get
                {
                    return Size;
                }
                set
                {
                    Size = value;
                }
            }
            /// <summary>
            /// Setting availability
            /// </summary>
            public bool AEUC_Enabled
            {
                get
                {
                    return Enabled;
                }
                set
                {
                    Enabled = value;
                }
            }
            /// <summary>
            /// Reference pointer
            /// </summary>
            public bool AEUC_RefPointer
            {
                get
                {
                    return aeuc_refPtr;
                }
                set
                {
                    aeuc_refPtr = value;
                }
            }
            /// <summary>
            /// Whether this control is state sensitive
            /// </summary>
            public bool AEUC_SupportStateSense
            {
                get
                {
                    return false;
                }
                set
                {
                    return;
                }
            }
            /// <summary>
            /// Set control's state as changed
            /// </summary>
            public void AEUC_SetStateChange(bool do_itter)
            {
                return;
            }
            /// <summary>
            /// Reset the control's state to initial value
            /// </summary>
            public void AEUC_ResetToDefault()
            {
                Val = ValDef;
            }
            /// <summary>
            /// Gets an AEUC-setting based on the current control settings
            /// </summary>
            /// <returns>A generic AEUC-Setting representation</returns>
            public GenAEUCSetting AEUC_GetSetting()
            {
                GenAEUCSetting crntSettings = new GenAEUCSetting();
                crntSettings.AEUC_id = Id;
                crntSettings.AEUC_size = Size;
                crntSettings.AEUC_val = new byte[Size];

                for (int i = 0; i < Size; i++)
                {
                    crntSettings.AEUC_val[i] = (byte)(Val >> (i * 8));
                }

                return crntSettings;
            }
            /// <summary>
            /// Indicates whether this control is part of a linked setting chain
            /// </summary>
            public bool AEUC_LinkedSetting
            {
                get
                {
                    return false;
                }
                set
                {
                    return;
                }
            }
            /// <summary>
            /// Get or set the next setting in the chain link
            /// </summary>
            public IAEUCSetting AEUC_NextSettingLink
            {
                get
                {
                    return null;
                }
                set
                {
                    return;
                }
            }
            /// <summary>
            /// Get or set the link setting chain type: bitfield or stuffing
            /// </summary>
            public int AEUC_SettingChainType
            {
                get
                {
                    return 0;
                }
                set
                {
                    return;
                }
            }
            /// <summary>
            /// Recursive itteration in the linked group to obtain a composite value
            /// </summary>
            /// <returns>Integer value</returns>
            public long AEUC_LinkValueAgregation()
            {
                return Val;
            }
            /// <summary>
            /// Recursive itteration in the linked group to set a composite value
            /// </summary>
            /// <returns>Integer value</returns>
            public void AEUC_LinkValueSetValue(long l_val)
            {
                Val = l_val;
            }
            /// <summary>
            /// Get or set the auxiliary status of the control
            /// </summary>
            public bool AEUC_AUXSetting
            {
                get
                {
                    return false;
                }
                set
                {
                    return;
                }
            }
            /// <summary>
            /// Get or set the control linked to the primary value of this auxiliary setting
            /// </summary>
            public IAEUCSetting AEUC_SettingPrimaryLink
            {
                get
                {
                    return null;
                }
                set
                {
                    return;
                }
            }
            /// <summary>
            /// Get or set the control linked to the secondary value of this auxiliary setting
            /// </summary>
            public IAEUCSetting AEUC_SettingSecondaryLink
            {
                get
                {
                    return null;
                }
                set
                {
                    return;
                }
            }
            /// <summary>
            /// Restore the setting value to its shadowed copy
            /// </summary>
            public void AEUC_RestoreShadowedValue()
            {
                return;
            }
            /// <summary>
            /// Update the shadowed copy of a setting to its new value
            /// </summary>
            public void AEUC_UpdateShadowedValue()
            {
                return;
            }
            /// <summary>
            /// Get or set the use of shadowed copy for this settig
            /// </summary>
            public bool AEUC_ShadowedValue
            {
                get
                {
                    return false;
                }
                set
                {
                    return;
                }
            }
            /// <summary>
            /// Get or set the display string of the control
            /// </summary>
            public string AEUC_DisplayName
            {
                get
                {
                    return DisplayName;
                }
                set
                {
                    DisplayName = value;
                }
            }
            /// <summary>
            /// When the control array is deserialized from a stream, this function will set the appropirate control links
            /// </summary>
            /// <returns>True if the operation completed successfully</returns>
            public bool AEUC_SetLinkInitialization()
            {
                return true;
            }
            /// <summary>
            /// Returns the reference to the valid AEUC setting object
            /// </summary>
            /// <returns>vali AEUC setting object</returns>
            public IAEUCSetting AEUC_GetLinkReference()
            {
                return this;
            }

            #endregion
        }

        /// <summary>
        /// Parameter structure display text
        /// </summary>
        public string dispName = "Empty parameter structure";

        uint STRCT_CSTM_HDR;

        /// <summary>
        /// List of all of the parameter fields that belong to that parameter structure
        /// </summary>
        GenAEUCSetting[] structContents;
        
        /// <summary>
        /// Flag indicating if this structure can be editted run time
        /// </summary>
        public bool Editable = false;
        /// <summary>
        /// Public accessor for structContents
        /// </summary>
        public GenAEUCSetting[] StructContents
        {
            get
            {
                if (structContents == null)
                    return null;

                GenAEUCSetting[] tmpRef = new GenAEUCSetting[structContents.Length];
                for (int i = 0; i < tmpRef.Length; i++)
                {
                    tmpRef[i] = new GenAEUCSetting();
                    tmpRef[i].AEUC_id = structContents[i].AEUC_id;
                    tmpRef[i].AEUC_size = structContents[i].AEUC_size;
                    tmpRef[i].AEUC_signed = structContents[i].AEUC_signed;
                    tmpRef[i].AEUC_pointer = structContents[i].AEUC_pointer;
                    tmpRef[i].AEUC_val = new byte[tmpRef[i].AEUC_size];
                    for(int k = 0; k < tmpRef[i].AEUC_size; k++)
                        tmpRef[i].AEUC_val[k] = structContents[i].AEUC_val[k];
                }

                return tmpRef;
            }
            set
            {
                GenAEUCSetting[] tmpRef = new GenAEUCSetting[value.Length];
                for (int i = 0; i < tmpRef.Length; i++)
                {
                    tmpRef[i] = new GenAEUCSetting();
                    tmpRef[i].AEUC_id = value[i].AEUC_id;
                    tmpRef[i].AEUC_size = value[i].AEUC_size;
                    tmpRef[i].AEUC_val = new byte[tmpRef[i].AEUC_size];
                    for (int k = 0; k < tmpRef[i].AEUC_size; k++)
                        tmpRef[i].AEUC_val[k] = value[i].AEUC_val[k];
                }

                structContents = tmpRef;
            }
        }
        /// <summary>
        /// Public accessor for structContents, applying struct header offset
        /// </summary>
        public GenAEUCSetting[] StructContentsForcedOffset
        {
            get
            {
                if (structContents == null)
                    return null;

                GenAEUCSetting[] tmpRef = new GenAEUCSetting[structContents.Length];
                for (int i = 0; i < tmpRef.Length; i++)
                {
                    tmpRef[i] = new GenAEUCSetting();
                    tmpRef[i].AEUC_id = structContents[i].AEUC_id - STRCT_CSTM_HDR;
                    tmpRef[i].AEUC_size = structContents[i].AEUC_size;
                    tmpRef[i].AEUC_val = new byte[tmpRef[i].AEUC_size];
                    for (int k = 0; k < tmpRef[i].AEUC_size; k++)
                        tmpRef[i].AEUC_val[k] = structContents[i].AEUC_val[k];
                }

                return tmpRef;
            }
            set
            {
                GenAEUCSetting[] tmpRef = new GenAEUCSetting[value.Length];
                for (int i = 0; i < tmpRef.Length; i++)
                {
                    tmpRef[i].AEUC_id = value[i].AEUC_id + STRCT_CSTM_HDR;
                    tmpRef[i].AEUC_size = value[i].AEUC_size;
                    for (int k = 0; k < tmpRef[i].AEUC_size; k++)
                        tmpRef[i].AEUC_val[k] = value[i].AEUC_val[k];
                }

                structContents = tmpRef;
            }
        }
        /// <summary>
        /// The associated string representation of the parameter structre's parameter ids.
        /// </summary>
        public GenPayloadStructParamNameResolve[] structContentsStringRep;

        /// <summary>
        /// Constructor for parameter structure payload type
        /// </summary>
        /// <param name="structName">Struct display name</param>
        /// <param name="sourceAEUC">Source AEUC interface compatible elemet array</param>
        /// <param name="compId">Structure's component id</param>
        /// <param name="structId">Structure's id</param>
        /// <param name="portNum">Structure's port number</param>
        public GenPayloadStruct(string structName, IAEUCSetting[] sourceAEUC, UInt64 compId, UInt64 structId, UInt64 portNum)
        {
            dispName = structName;
            int hdrItems = 0;
            STRCT_CSTM_HDR = 4;

            int sourceSettCount = 0;

            if (sourceAEUC != null)
                sourceSettCount = (int)(sourceAEUC.Length + STRCT_CSTM_HDR);
            else
                sourceSettCount = (int)STRCT_CSTM_HDR;

            structContents = new GenAEUCSetting[sourceSettCount];
            GenAEUCSetting[] sourceStrCont;
            structContentsStringRep = new GenPayloadStructParamNameResolve[sourceSettCount];
            GenPayloadStructParamNameResolve[] sourceStrContStringRep;

            #region Component id
            structContents[hdrItems] = new GenAEUCSetting();
            structContents[hdrItems].AEUC_id = (uint)hdrItems;
            structContents[hdrItems].AEUC_size = 4;
            structContents[hdrItems].AEUC_val = new byte[structContents[hdrItems].AEUC_size];
            for (int i = 0; i < structContents[hdrItems].AEUC_size; i++)
                structContents[hdrItems].AEUC_val[i] = (byte)(compId >> (8 * i));

            structContentsStringRep[hdrItems] = new GenPayloadStructParamNameResolve();
            structContentsStringRep[hdrItems].paramId = (uint)hdrItems;
            structContentsStringRep[hdrItems].dispName = "compId";
            hdrItems++;
            #endregion

            #region Struct id
            structContents[hdrItems] = new GenAEUCSetting();
            structContents[hdrItems].AEUC_id = (uint)hdrItems;
            structContents[hdrItems].AEUC_size = 4;
            structContents[hdrItems].AEUC_val = new byte[structContents[hdrItems].AEUC_size];
            for (int i = 0; i < structContents[hdrItems].AEUC_size; i++)
                structContents[hdrItems].AEUC_val[i] = (byte)(structId >> (8 * i));

            structContentsStringRep[hdrItems] = new GenPayloadStructParamNameResolve();
            structContentsStringRep[hdrItems].paramId = (uint)hdrItems;
            structContentsStringRep[hdrItems].dispName = "structId";
            hdrItems++;
            #endregion

            #region Struct size
            structContents[hdrItems] = new GenAEUCSetting();
            structContents[hdrItems].AEUC_id = (uint)hdrItems;
            structContents[hdrItems].AEUC_size = 4;
            structContents[hdrItems].AEUC_val = new byte[structContents[hdrItems].AEUC_size];
            for (int i = 0; i < structContents[hdrItems].AEUC_size; i++)
                structContents[hdrItems].AEUC_val[i] = (byte)(0 >> (8 * i));

            structContentsStringRep[hdrItems] = new GenPayloadStructParamNameResolve();
            structContentsStringRep[hdrItems].paramId = (uint)hdrItems;
            structContentsStringRep[hdrItems].dispName = "structSizeSystemParameter";
            hdrItems++;
            #endregion

            #region Port number
            structContents[hdrItems] = new GenAEUCSetting();
            structContents[hdrItems].AEUC_id = (uint)hdrItems;
            structContents[hdrItems].AEUC_size = 4;
            structContents[hdrItems].AEUC_val = new byte[structContents[hdrItems].AEUC_size];
            for (int i = 0; i < structContents[hdrItems].AEUC_size; i++)
                structContents[hdrItems].AEUC_val[i] = (byte)(portNum >> (8 * i));

            structContentsStringRep[hdrItems] = new GenPayloadStructParamNameResolve();
            structContentsStringRep[hdrItems].paramId = (uint)hdrItems;
            structContentsStringRep[hdrItems].dispName = "portNum";
            hdrItems++;
            #endregion

            if (sourceAEUC != null)
            {
                prepareFrom(sourceAEUC, STRCT_CSTM_HDR, out sourceStrCont, out sourceStrContStringRep);

                sourceStrCont.CopyTo(structContents, STRCT_CSTM_HDR);

                sourceStrContStringRep.CopyTo(structContentsStringRep, STRCT_CSTM_HDR);
            }
        }

        /// <summary>
        /// Constructor for parameter structure payload type
        /// </summary>
        /// <param name="structName">Struct display name</param>
        /// <param name="sourceAEUC">Source AEUC interface compatible elemet array</param>
        public GenPayloadStruct(string structName, IAEUCSetting[] sourceAEUC)
        {
            dispName = structName;
            STRCT_CSTM_HDR = 0;

            if (sourceAEUC != null)
            {
                structContents = new GenAEUCSetting[sourceAEUC.Length];
                GenAEUCSetting[] sourceStrCont;
                structContentsStringRep = new GenPayloadStructParamNameResolve[sourceAEUC.Length];
                GenPayloadStructParamNameResolve[] sourceStrContStringRep;

                prepareFrom(sourceAEUC, STRCT_CSTM_HDR, out sourceStrCont, out sourceStrContStringRep);

                sourceStrCont.CopyTo(structContents, STRCT_CSTM_HDR);

                sourceStrContStringRep.CopyTo(structContentsStringRep, STRCT_CSTM_HDR);
            }
            else
            {
                structContents = new GenAEUCSetting[0];
                structContentsStringRep = new GenPayloadStructParamNameResolve[0];
            }
        }

        /// <summary>
        /// Indexer to directly access a parameter integer value by the parameter's id
        /// </summary>
        /// <param name="paramId">Id of the parameter that is to be accessed</param>
        /// <returns>Unsigned long value of the parameter</returns>
        public Object this[UInt64 paramId]
        {
            get
            {
                if (structContents == null)
                    throw new Exception(dispName + " parameter structure contents not set!");

                for (int i = 0; i < structContents.Length; i++)
                {
                    if (structContents[i].AEUC_id == paramId)
                    {
                        switch (structContents[i].AEUC_size)
                        {
                            case 1:
                                {
                                    Byte tmpVal = 0;
                                    for (int k = 0; k < structContents[i].AEUC_size; k++)
                                        tmpVal |= (Byte)(structContents[i].AEUC_val[k] << (8 * k));
                                    if (structContents[i].AEUC_signed)
                                        return (char)tmpVal;
                                    else
                                        return tmpVal;
                                }
                            case 2:
                                {
                                    UInt16 tmpVal = 0;
                                    for (int k = 0; k < structContents[i].AEUC_size; k++)
                                        tmpVal |= (UInt16)(structContents[i].AEUC_val[k] << (8 * k));
                                    if (structContents[i].AEUC_signed)
                                        return (Int16)tmpVal;
                                    else
                                        return tmpVal;
                                }
                            case 4:
                                {
                                    UInt32 tmpVal = 0;
                                    for (int k = 0; k < structContents[i].AEUC_size; k++)
                                        tmpVal |= (UInt32)((uint)(structContents[i].AEUC_val[k] << (8 * k)));
                                    if (structContents[i].AEUC_signed)
                                        return (Int32)tmpVal;
                                    else
                                        return tmpVal;
                                }
                            default:
                                {
                                    Byte[] tmpVal = new Byte[structContents[i].AEUC_size];
                                    for (int k = 0; k < structContents[i].AEUC_size; k++)
                                        tmpVal[k] = ((Byte)structContents[i].AEUC_val[k]);

                                    return tmpVal;
                                }
                        }
                    }
                }
                throw new Exception(dispName + " invalid parameter id " + paramId.ToString());
            }
            set
            {
                if (structContents == null)
                    throw new Exception(dispName + " parameter structure contents not set!");

                for (int i = 0; i < structContents.Length; i++)
                {
                    if (structContents[i].AEUC_id == paramId)
                    {
                        Int64 tmpVal = 0;
                        
                        if(value.GetType() == typeof(Byte))
                        {
                            tmpVal = (Int64)((Byte)value);
                        }
                        else if (value.GetType() == typeof(Int16))
                        {
                            tmpVal = (Int64)((Int16)value);
                        }
                        else if (value.GetType() == typeof(UInt16))
                        {
                            tmpVal = (Int64)((UInt16)value);
                        }
                        else if (value.GetType() == typeof(UInt32))
                        {
                            tmpVal = (Int64)((UInt32)value);
                        }
                        else if (value.GetType() == typeof(Int32))
                        {
                            tmpVal = (Int64)((Int32)value);
                        }
                        else if (value.GetType() == typeof(Int64))
                        {
                            tmpVal = (Int64)value;
                        }
                        else if (value.GetType() == typeof(Byte[]))
                        {
                            Byte[] tmpBArr = (Byte[])value;
                            structContents[i].AEUC_size = (uint)(tmpBArr.Length);
                            structContents[i].AEUC_val = new byte[structContents[i].AEUC_size];
                            for (int k = 0; k < tmpBArr.Length; k++)
                                structContents[i].AEUC_val[k] = (Byte)(tmpBArr[k]);

                            return;
                        }
                        else
                        {
                            throw new Exception("Cannot assign object of type " + value.GetType().ToString() + " to the payload container.");
                        }

                        if (tmpVal < 0)
                            structContents[i].AEUC_signed = true;
                        else
                            structContents[i].AEUC_signed = false;

                        for (int k = 0; k < structContents[i].AEUC_size; k++)
                            structContents[i].AEUC_val[k] = (byte)(tmpVal >> (8 * k));

                        return;
                    }
                }
                throw new Exception(dispName + " invalid parameter id " + paramId.ToString());
            }
        }
        /// <summary>
        /// Indexer to directly access a parameter string value by the parameter's id
        /// </summary>
        /// <param name="paramId">Id of the parameter that is to be accessed</param>
        /// <returns>String value of the parameter</returns>
        public string getParamStringVal(UInt64 paramId)
        {
            if (structContents == null)
                throw new Exception(dispName + " parameter structure contents not set!");

            for (int i = 0; i < structContents.Length; i++)
            {
                if (structContents[i].AEUC_id == paramId)
                {
                    string strVal = "";
                    for (int ik = 0; ik < structContents[i].AEUC_size && structContents[i].AEUC_val[ik] != '\0'; ik++)
                    {
                        strVal += (char)structContents[i].AEUC_val[ik];
                    }

                    return strVal;
                }
            }

            throw new Exception(dispName + " invalid parameter id " + paramId.ToString());
        }

        /// <summary>
        /// Indexer to obtain a parameter's id by it's string representation
        /// </summary>
        /// <param name="paramId">Text value of the parameter that is to be accessed</param>
        /// <returns>Unsigned long id of the parameter</returns>
        public UInt64 this[string paramId]
        {
            get
            {
                if (structContents == null || structContentsStringRep == null)
                    throw new Exception(dispName + " parameter structure contents not set!");

                for (int i = 0; i < structContentsStringRep.Length; i++)
                {
                    if (structContentsStringRep[i].dispName == paramId)
                    {
                        return structContentsStringRep[i].paramId;
                    }
                }
                throw new Exception(dispName + " invalid parameter id " + paramId);
            }
        }

        /// <summary>
        /// Generates genAUECSetting and ScrParamStructParamNameResolve from an IAEUCSetting compatible element array
        /// </summary>
        /// <param name="sourceAEUC">Source AEUC interface compatible elemet array</param>
        /// <param name="applyOffst">Any element id offset to be introduced (0 for none...)</param>
        /// <param name="genSettOut">Out general AEUC setting element array</param>
        /// <param name="genIdResolveMap">Out text to id mapping element array</param>
        void prepareFrom(IAEUCSetting[] sourceAEUC, uint applyOffst, out GenAEUCSetting[] genSettOut, out GenPayloadStructParamNameResolve[] genIdResolveMap)
        {
            genSettOut = new GenAEUCSetting[sourceAEUC.Length];
            genIdResolveMap = new GenPayloadStructParamNameResolve[sourceAEUC.Length];

            try
            {
                //Obtain all of the settings that are to be transfered
                for (int i = 0; i < sourceAEUC.Length; i++)
                {
                    if (sourceAEUC[i].AEUC_Enabled)
                    {
                        sourceAEUC[i].AEUC_SetStateChange(true);
                        genSettOut[i] = sourceAEUC[i].AEUC_GetSetting();
                        if (genSettOut[i] != null)
                        {
                            genSettOut[i].AEUC_id += applyOffst;

                            genIdResolveMap[i] = new GenPayloadStructParamNameResolve();
                            genIdResolveMap[i].dispName = sourceAEUC[i].AEUC_DisplayName;
                            genIdResolveMap[i].paramId = sourceAEUC[i].AEUC_Id + applyOffst;
                        }
                        else
                        {
                            throw new Exception("Error creating payload object from the specified AEUC settings!\n" +
                                                    sourceAEUC[i].AEUC_DisplayName + " setting couldn't create common payload setting object!");
                        }
                    }
                }
            }
            catch(Exception ex)
            {
                throw new Exception("Error creating payload object from the specified AEUC settings!\nException thrown: " + ex.Message);
            }
            object[] test;
            test = Auxiliaries.MergeSort.merge_sort(genSettOut, 0, genSettOut.Length - 1);
            for (int i = 0; i < test.Length; i++)
                genSettOut[i] = (GenAEUCSetting)test[i];
            test = Auxiliaries.MergeSort.merge_sort(genIdResolveMap, 0, genIdResolveMap.Length - 1);
            for (int i = 0; i < test.Length; i++)
                genIdResolveMap[i] = (GenPayloadStructParamNameResolve)test[i];
        }
        /// <summary>
        /// Adds a range of items to the current payload items array
        /// </summary>
        /// <param name="AEUCItems">Array of items to add</param>
        /// <param name="applyOffst">Any element id offset to be introduced (0 for none...)</param>
        /// <param name="genSettOut">Reference general AEUC setting element array</param>
        /// <param name="genIdResolveMap">Reference text to id mapping element array</param>
        void setPayloadItems(IAEUCSetting[] AEUCItems, uint applyOffst, ref GenAEUCSetting[] genSettOut, ref GenPayloadStructParamNameResolve[] genIdResolveMap)
        {
            if (genSettOut.Length != genIdResolveMap.Length)
                throw new Exception(dispName + " unexpected error occured!");

            int crntPldSize = genSettOut.Length;
            GenAEUCSetting[] tmpGenSettOut = new GenAEUCSetting[crntPldSize + AEUCItems.Length];
            GenPayloadStructParamNameResolve[] tmpGenIdResolveMap = new GenPayloadStructParamNameResolve[crntPldSize + AEUCItems.Length];

            genSettOut.CopyTo(tmpGenSettOut, 0);
            genIdResolveMap.CopyTo(tmpGenIdResolveMap, 0);

            //Obtain all of the settings that are to be transfered
            for (int i = 0; i < AEUCItems.Length; i++)
            {
                if (AEUCItems[i].AEUC_Enabled)
                {
                    tmpGenSettOut[crntPldSize + i] = AEUCItems[i].AEUC_GetSetting();
                    tmpGenSettOut[crntPldSize + i].AEUC_id += applyOffst;

                    tmpGenIdResolveMap[crntPldSize + i] = new GenPayloadStructParamNameResolve();
                    tmpGenIdResolveMap[crntPldSize + i].dispName = AEUCItems[i].AEUC_DisplayName;
                    tmpGenIdResolveMap[crntPldSize + i].paramId = AEUCItems[i].AEUC_Id + applyOffst;
                }
            }
            object[] test;
            test = MergeSort.merge_sort(tmpGenSettOut, 0, tmpGenSettOut.Length - 1);
            for (int i = 0; i < test.Length; i++)
                tmpGenSettOut[i] = (GenAEUCSetting)test[i];
            test = MergeSort.merge_sort(tmpGenIdResolveMap, 0, tmpGenIdResolveMap.Length - 1);
            for (int i = 0; i < test.Length; i++)
                tmpGenIdResolveMap[i] = (GenPayloadStructParamNameResolve)test[i];

            genSettOut = tmpGenSettOut;
            genIdResolveMap = tmpGenIdResolveMap;
        }
        /// <summary>
        /// Adss an array of items to the current payload struct
        /// </summary>
        /// <param name="pldAEUCItems">Array of items to add</param>
        public void SetPayloadItems(IAEUCSetting[] pldAEUCItems)
        {
            setPayloadItems(pldAEUCItems, STRCT_CSTM_HDR, ref structContents, ref structContentsStringRep);
        }
        /// <summary>
        /// Adds a range of items to the current payload items
        /// </summary>
        /// <param name="pldItems">GenAEUCSetting items to add</param>
        /// <param name="pldStringRep">String reference of the items to add</param>
        /// <param name="genSettOut">Reference general AEUC setting element array</param>
        /// <param name="genIdResolveMap">Reference text to id mapping element array</param>
        void addPayloadItems(GenAEUCSetting[] pldItems, GenPayloadStructParamNameResolve[] pldStringRep, ref GenAEUCSetting[] genSettOut, ref GenPayloadStructParamNameResolve[] genIdResolveMap)
        {
            if (genSettOut.Length != genIdResolveMap.Length || pldItems.Length != pldStringRep.Length)
                throw new Exception(dispName + " unexpected error occured!");

            int crntPldSize = genSettOut.Length;
            uint applyOffst = (uint)crntPldSize;
            GenAEUCSetting[] tmpGenSettOut = new GenAEUCSetting[crntPldSize + pldItems.Length];
            GenPayloadStructParamNameResolve[] tmpGenIdResolveMap = new GenPayloadStructParamNameResolve[crntPldSize + pldItems.Length]; 

            genSettOut.CopyTo(tmpGenSettOut, 0);
            genIdResolveMap.CopyTo(tmpGenIdResolveMap, 0);

            //Obtain all of the settings that are to be transfered
            for (int i = 0; i < pldItems.Length; i++)
            {
                tmpGenSettOut[crntPldSize + i] = pldItems[i];
                tmpGenSettOut[crntPldSize + i].AEUC_id += applyOffst;

                tmpGenIdResolveMap[crntPldSize + i] = new GenPayloadStructParamNameResolve();
                tmpGenIdResolveMap[crntPldSize + i].dispName = pldStringRep[i].dispName;
                tmpGenIdResolveMap[crntPldSize + i].paramId = pldStringRep[i].paramId + applyOffst;
            }
            object[] test;
            test = MergeSort.merge_sort(tmpGenSettOut, 0, tmpGenSettOut.Length - 1);
            for (int i = 0; i < test.Length; i++)
                tmpGenSettOut[i] = (GenAEUCSetting)test[i];
            test = MergeSort.merge_sort(tmpGenIdResolveMap, 0, tmpGenIdResolveMap.Length - 1);
            for (int i = 0; i < test.Length; i++)
                tmpGenIdResolveMap[i] = (GenPayloadStructParamNameResolve)test[i];

            genSettOut = tmpGenSettOut;
            genIdResolveMap = tmpGenIdResolveMap;
        }
        /// <summary>
        /// Adss an array of items to the current payload struct
        /// </summary>
        /// <param name="pldItems">Array of items to add</param>
        /// <param name="pldStringRep">Array of string reference items to add</param>
        public void AddPayloadItems(GenAEUCSetting[] pldItems, GenPayloadStructParamNameResolve[] pldStringRep)
        {
            addPayloadItems(pldItems, pldStringRep, ref structContents, ref structContentsStringRep);
        }
        /// <summary>
        /// Adds a range of items to the current payload items array
        /// </summary>
        /// <param name="txtItem">String text to add as payload item</param>
        /// <param name="applyOffst">Any element id offset to be introduced (0 for none...)</param>
        /// <param name="genSettOut">Reference general AEUC setting element array</param>
        /// <param name="genIdResolveMap">Reference text to id mapping element array</param>
        void addPayloadStringItem(string txtItem, uint applyOffst, ref GenAEUCSetting[] genSettOut, ref GenPayloadStructParamNameResolve[] genIdResolveMap)
        {
            if (genSettOut.Length != genIdResolveMap.Length)
                throw new Exception(dispName + " unexpected error occured!");

            int crntPldSize = genSettOut.Length;
            GenAEUCSetting[] tmpGenSettOut = new GenAEUCSetting[crntPldSize + 1];
            GenPayloadStructParamNameResolve[] tmpGenIdResolveMap = new GenPayloadStructParamNameResolve[crntPldSize + 1];

            genSettOut.CopyTo(tmpGenSettOut, 0);
            genIdResolveMap.CopyTo(tmpGenIdResolveMap, 0);

            GenAEUCSetting compName = new GenAEUCSetting();
            if (crntPldSize > 0)
                compName.AEUC_id = tmpGenSettOut[crntPldSize - 1].AEUC_id++;
            else
                compName.AEUC_id = 0;
            compName.AEUC_size = (uint)(txtItem.Length + 1);
            compName.AEUC_val = new byte[compName.AEUC_size];
            for (int i = 0; i < txtItem.Length; i++)
                compName.AEUC_val[i] = (byte)(txtItem[i]);
            compName.AEUC_val[compName.AEUC_size - 1] = (byte)('\0');

            tmpGenSettOut[crntPldSize] = compName;
            tmpGenSettOut[crntPldSize].AEUC_id += applyOffst;

            tmpGenIdResolveMap[crntPldSize] = new GenPayloadStructParamNameResolve();
            tmpGenIdResolveMap[crntPldSize].dispName = "String value";
            tmpGenIdResolveMap[crntPldSize].paramId = compName.AEUC_id;

            object[] test;
            test = MergeSort.merge_sort(tmpGenSettOut, 0, tmpGenSettOut.Length - 1);
            for (int i = 0; i < test.Length; i++)
                tmpGenSettOut[i] = (GenAEUCSetting)test[i];
            test = MergeSort.merge_sort(tmpGenIdResolveMap, 0, tmpGenIdResolveMap.Length - 1);
            for (int i = 0; i < test.Length; i++)
                tmpGenIdResolveMap[i] = (GenPayloadStructParamNameResolve)test[i];

            genSettOut = tmpGenSettOut;
            genIdResolveMap = tmpGenIdResolveMap;
        }
        /// <summary>
        /// Sets a string value to an existing parameter
        /// </summary>
        /// <param name="paramId">Id of the parameter that is to be accessed</param>
        /// <param name="txtItem">String value to set as parameter value</param>
        public void setStringItem(UInt64 paramId, string txtItem)
        {
            if (structContents == null)
                throw new Exception(dispName + " parameter structure contents not set!");

            for (int i = 0; i < structContents.Length; i++)
            {
                if (structContents[i].AEUC_id == paramId)
                {
                    structContents[i].AEUC_size = (uint)(txtItem.Length + 1);
                    structContents[i].AEUC_val = new byte[structContents[i].AEUC_size];
                    for (int k = 0; k < txtItem.Length; k++)
                        structContents[i].AEUC_val[k] = (byte)(txtItem[k]);
                    structContents[i].AEUC_val[structContents[i].AEUC_size - 1] = (byte)('\0');
                    return;
                }
            }
            throw new Exception(dispName + " invalid parameter id " + paramId.ToString());
        }
        /// <summary>
        /// Adss a string item to the current payload struct
        /// </summary>
        /// <param name="txtItem">String text to add as payload item</param>
        public void AddPayloadStringItem(string txtItem)
        {
            addPayloadStringItem(txtItem, STRCT_CSTM_HDR, ref structContents, ref structContentsStringRep);
        }

        /// <summary>
        /// Serialization base address offset mapping
        /// </summary>
        public class srzOfstMap
        {
            /// <summary>
            /// Payload id
            /// </summary>
            public uint id;
            /// <summary>
            /// Base address offset
            /// </summary>
            public uint ofst;
        }

        /// <summary>
        /// Creates a byte array of the message payload bytestream withouth the custom OMXConfigurationTool header
        /// </summary>
        /// <returns>Structure bytestream</returns>
        public byte[] preparePureByteStream()
        {
            if (STRCT_CSTM_HDR > 0)
            {
                GenAEUCSetting[] pureArr = new GenAEUCSetting[structContents.Length - STRCT_CSTM_HDR];
                for (int i = 0; i < pureArr.Length; i++)
                {
                    pureArr[i] = structContents[STRCT_CSTM_HDR + i];
                }
                return structAlignedBytestreamPrep(structContents);
            }
            else
            {
                return structAlignedBytestreamPrep(structContents);
            }
        }

        /// <summary>
        /// Creates a byte array of the message payload bytestream
        /// </summary>
        /// <returns>Payload bytestream</returns>
        public byte[] prepareByteStream()
        {
            return structAlignedBytestreamPrep(structContents);
        }

        /// <summary>
        /// Creates a byte array of the message payload bytestream serializing structure pointers
        /// </summary>
        /// <param name="baseAddress">Serialization base address</param>
        /// <param name="serializationMap">Serialization map</param>
        /// <returns>Payload bytestream</returns>
        public byte[] prepareByteStream(srzOfstMap[] serializationMap)
        {
            return structAlignedBytestreamPrep(structContents, serializationMap);
        }

        /// <summary>
        /// Prepares a list of GenAEUCSetting arrays that represent Parameters structure bytestreams packed together.
        /// </summary>
        /// <param name="accSettVals">An array of the accumulated AEUCGenSetting objects that must be transfered</param>
        /// <returns>A list of AEUCGenSetting arrays representing separete Parameters structure bytestreams to transfer</returns>
        byte[] structAlignedBytestreamPrep(GenAEUCSetting[] accSettVals)
        {
            int streamPos = 0;
            int totalStructSize = 0;
            #region First run  - determine the length of the bytestream.
            for (int i = 0; i < accSettVals.Length; i++)
            {
                switch (accSettVals[i].AEUC_size)
                {
                    case 1:
                        totalStructSize++;
                        break;
                    case 2:
                        if (totalStructSize % 2 > 0)
                            totalStructSize++;

                        totalStructSize += 2;
                        break;
                    case 4:
                        int align = totalStructSize % 4;
                        if (align == 0)
                            align = 4;
                        while (4 - align++ > 0)
                            totalStructSize++;

                        totalStructSize += 4;
                        break;
                    default:
                        totalStructSize += (int)accSettVals[i].AEUC_size;
                        break;
                        //throw new Exception(dispName + " - setting with id " + accSettVals[i].AEUC_id.ToString() + " has invalid size of " + accSettVals[i].AEUC_size.ToString());
                }
            }
            #endregion
            try
            {
                this[this["structSizeSystemParameter"]] = (totalStructSize + 3) & ~3;
            }
            catch
            {
            }
            byte[] structByteStream = new byte[totalStructSize];
            #region Second run  - set all of the respective values in the prepared bytestream.
            for (int i = 0; i < accSettVals.Length; i++)
            {
                switch (accSettVals[i].AEUC_size)
                {
                    case 1:
                        structByteStream[streamPos++] = accSettVals[i].AEUC_val[0];
                        break;
                    case 2:
                        if (streamPos % 2 > 0)
                            structByteStream[streamPos++] = 0;

                        structByteStream[streamPos++] = accSettVals[i].AEUC_val[0];
                        structByteStream[streamPos++] = accSettVals[i].AEUC_val[1];
                        break;
                    case 4:
                        int align = streamPos % 4;
                        if (align == 0)
                            align = 4;
                        while (4 - align++ > 0)
                            structByteStream[streamPos++] = 0;

                        structByteStream[streamPos++] = accSettVals[i].AEUC_val[0];
                        structByteStream[streamPos++] = accSettVals[i].AEUC_val[1];
                        structByteStream[streamPos++] = accSettVals[i].AEUC_val[2];
                        structByteStream[streamPos++] = accSettVals[i].AEUC_val[3];
                        break;
                    default:
                        for (int ikItr = 0; ikItr < accSettVals[i].AEUC_size; ikItr++)
                        {
                            structByteStream[streamPos++] = accSettVals[i].AEUC_val[ikItr];
                        }
                        break;
                }
            }
            #endregion
            return structByteStream;
        }

        /// <summary>
        /// Prepares a list of GenAEUCSetting arrays that represent Parameters structure bytestreams packed together.
        /// </summary>
        /// <param name="accSettVals">An array of the accumulated AEUCGenSetting objects that must be transfered</param>
        /// <param name="serializationMap">An array of the base address to structure id mapping used for serialization</param>
        /// <returns>A list of AEUCGenSetting arrays representing separete Parameters structure bytestreams to transfer</returns>
        byte[] structAlignedBytestreamPrep(GenAEUCSetting[] accSettVals, srzOfstMap[] serializationMap)
        {
            int streamPos = 0;
            int totalStructSize = 0;
            #region First run  - determine the length of the bytestream.
            for (int i = 0; i < accSettVals.Length; i++)
            {
                switch (accSettVals[i].AEUC_size)
                {
                    case 1:
                        totalStructSize++;
                        break;
                    case 2:
                        if (totalStructSize % 2 > 0)
                            totalStructSize++;

                        totalStructSize += 2;
                        break;
                    case 4:
                        int align = totalStructSize % 4;
                        if (align == 0)
                            align = 4;
                        while (4 - align++ > 0)
                            totalStructSize++;

                        totalStructSize += 4;
                        break;
                    default:
                        totalStructSize += (int)accSettVals[i].AEUC_size;
                        break;
                    //throw new Exception(dispName + " - setting with id " + accSettVals[i].AEUC_id.ToString() + " has invalid size of " + accSettVals[i].AEUC_size.ToString());
                }
            }
            #endregion
            try
            {
                this[this["structSizeSystemParameter"]] = (totalStructSize + 3) & ~3;
            }
            catch
            {
            }
            byte[] structByteStream = new byte[totalStructSize];
            #region Second run  - set all of the respective values in the prepared bytestream.
            for (int i = 0; i < accSettVals.Length; i++)
            {
                switch (accSettVals[i].AEUC_size)
                {
                    case 1:
                        structByteStream[streamPos++] = accSettVals[i].AEUC_val[0];
                        break;
                    case 2:
                        if (streamPos % 2 > 0)
                            structByteStream[streamPos++] = 0;

                        structByteStream[streamPos++] = accSettVals[i].AEUC_val[0];
                        structByteStream[streamPos++] = accSettVals[i].AEUC_val[1];
                        break;
                    case 4:
                        int align = streamPos % 4;
                        if (align == 0)
                            align = 4;
                        while (4 - align++ > 0)
                            structByteStream[streamPos++] = 0;

                        if (accSettVals[i].AEUC_pointer)
                        {
                            uint strId = 0;
                            uint strOfst = 0xFFFFFFFF;
                            for (int iAcc = 0; iAcc < 4; iAcc++)
                            {
                                strId |= (uint)(accSettVals[i].AEUC_val[iAcc]<<(iAcc*8));
                            }

                            for (int itr = 0; itr < serializationMap.Length; itr++)
                            {
                                if(serializationMap[itr].id == strId)
                                {
                                    strOfst = serializationMap[itr].ofst + STRCT_CSTM_HDR;
                                }
                            }

                            if (strOfst == 0xFFFFFFFF)
                            {
                                throw new Exception("Cannot find structure with id: " + strId.ToString() + " in the provided structures!");
                            }

                            structByteStream[streamPos++] = (byte)(strOfst >> 0);
                            structByteStream[streamPos++] = (byte)(strOfst >> 8);
                            structByteStream[streamPos++] = (byte)(strOfst >> 16);
                            structByteStream[streamPos++] = (byte)(strOfst >> 24);
                        }
                        else
                        {
                            structByteStream[streamPos++] = accSettVals[i].AEUC_val[0];
                            structByteStream[streamPos++] = accSettVals[i].AEUC_val[1];
                            structByteStream[streamPos++] = accSettVals[i].AEUC_val[2];
                            structByteStream[streamPos++] = accSettVals[i].AEUC_val[3];
                        }
                        break;
                    default:
                        for (int ikItr = 0; ikItr < accSettVals[i].AEUC_size; ikItr++)
                        {
                            structByteStream[streamPos++] = accSettVals[i].AEUC_val[ikItr];
                        }
                        break;
                }
            }
            #endregion
            return structByteStream;
        }

        /// <summary>
        /// Extract data from a byte array - bytestream payload
        /// </summary>
        /// <param name="byteStream">Array containing the payload data</param>
        public void parseByteStream(byte[] byteStream)
        {
            if (byteStream == null || byteStream.Length == 0)
                throw new Exception("Cannot parse empty bytestream!");

            int streamPos = 0;
            #region Read all of the values into the generated settings array
            for (int elNum = 0; elNum < structContents.Length; elNum++)
            {
                bool error = false;
                switch (structContents[elNum].AEUC_size)
                {
                    case 1:
                        if (byteStream.Length >= streamPos + 1)
                            structContents[elNum].AEUC_val[0] = byteStream[streamPos++];
                        else
                            error = true;
                        break;
                    case 2:
                        if (byteStream.Length >= streamPos + 2)
                        {
                            if (streamPos % 2 > 0)
                            {
                                streamPos++;
                            }
                            structContents[elNum].AEUC_val[0] = byteStream[streamPos++];
                            structContents[elNum].AEUC_val[1] = byteStream[streamPos++];
                        }
                        else
                            error = true;
                        break;
                    case 4:
                        if (byteStream.Length >= streamPos + 4)
                        {
                            int align = streamPos % 4;
                            if (align == 0)
                                align = 4;
                            while (4 - align++ > 0)
                            {
                                streamPos++;
                            }
                            structContents[elNum].AEUC_val[0] = byteStream[streamPos++];
                            structContents[elNum].AEUC_val[1] = byteStream[streamPos++];
                            structContents[elNum].AEUC_val[2] = byteStream[streamPos++];
                            structContents[elNum].AEUC_val[3] = byteStream[streamPos++];
                        }
                        else
                            error = true;
                        break;
                    default:
                        if (byteStream.Length >= streamPos + structContents[elNum].AEUC_size)
                        {
                            for (int ikItr = 0; ikItr < structContents[elNum].AEUC_size; ikItr++)
                            {
                                structContents[elNum].AEUC_val[ikItr] = byteStream[streamPos++];
                            }
                        }
                        else
                            error = true;
                        break;
                }

                if (error)
                {
                    throw new Exception("Received bytestream of size " +
                        byteStream.Length.ToString() +
                        " processed to position " +
                        streamPos.ToString() + ";" +
                        "Cannot read setting with id: " +
                        structContents[elNum].AEUC_id.ToString() +
                        " and size: " +
                        structContents[elNum].AEUC_size.ToString());
                }
            }
            #endregion
        }

        /// <summary>
        /// Overrided to string method
        /// </summary>
        /// <returns>Parameter structure's display text</returns>
        public override string ToString()
        {
            return dispName;
        }
        /// <summary>
        /// Generates a text summary of the parameter structure
        /// </summary>
        /// <returns>String containing summary information</returns>
        public string ContentsString(bool hex)
        {
            string contentsStr = dispName + "\n\n";

            if (structContents == null || structContents.Length == 0)
                return contentsStr + "Structure is empty!";

            for (int i = 0; i < structContentsStringRep.Length; i++)
            {

                contentsStr += structContentsStringRep[i].dispName;
                UInt64 id = this[structContentsStringRep[i].dispName];
                try
                {
                    Object tmp = this[id];
                    Int64 tmpVal = 0;

                    if (tmp.GetType() == typeof(Byte))
                    {
                        tmpVal = (Int64)((Byte)tmp);
                    }
                    else if (tmp.GetType() == typeof(UInt16))
                    {
                        tmpVal = (Int64)((UInt16)tmp);
                    }
                    else if (tmp.GetType() == typeof(UInt32))
                    {
                        tmpVal = (Int64)((UInt32)tmp);
                    }
                    else if (tmp.GetType() == typeof(Byte[]))
                    {
                        contentsStr += " id: " + id.ToString() + "; value: " + getParamStringVal(id) + ";\n";
                    }

                    if (hex)
                        contentsStr += " id: 0x" + HEX_converter.ToHexString((uint)id) + "; value: 0x" + HEX_converter.ToHexString(tmpVal) + ";\n";
                    else
                        contentsStr += " id: " + id.ToString() + "; value: " + tmpVal.ToString() + ";\n";
                }
                catch
                {
                    contentsStr += " id: " + id.ToString() + "; --can't parse value!\n";
                }
            }

            return contentsStr;
        }
    }

    /// <summary>
    /// Matches a parameter id - field structure address to a string representation
    /// </summary>
    public class GenPayloadStructParamNameResolve : Auxiliaries.MergeSort.IMergeSortable
    {
        /// <summary>
        /// Parameter display text
        /// </summary>
        public string dispName = "Undefined parameter";
        /// <summary>
        /// Parameter id - paramater structure field address
        /// </summary>
        public UInt64 paramId;

        /// <summary>
        /// Overrided to string method
        /// </summary>
        /// <returns>Parameter's display text</returns>
        public override string ToString()
        {
            return dispName;
        }

        #region IMergeSortable Members
        /// <summary>
        /// The IMergeSortable required comparisson argument
        /// </summary>
        public ulong argument
        {
            get { return paramId; }
        }

        #endregion
    }
}
